﻿using CommandLinex;
using N_m3u8DL_RE.CommandLinex;
using N_m3u8DL_RE.Common.Log;
using N_m3u8DL_RE.Enums;

namespace N_m3u8DL_RE.Entity;

public class DownloadArgument
{
    [Argument("input", Description = "链接或文件",IsRequired = true)]
    public string Input { get; set; } = default!;

    [Argument("header", Description = "为HTTP请求设置特定的请求头,Json格式", IsRequired = false,ProcessorType = typeof(HeaderValueProcessor))]
    public Dictionary<string, string> Headers { get; set; } = new Dictionary<string, string>();
    
    [Argument("ad-keyword", Description = "用户自定义广告分片URL关键字", IsRequired = false,ProcessorType = typeof(StringArrayValueProcessor))]
    public string[]? AdKeywords { get; set; }
    [Argument("max-speed", Description = "设置限速，单位支持 Mbps 或 Kbps，如：15M 100K", IsRequired = false)]
    public long? MaxSpeed { get; set; }
    
    [Argument("key", Description = "设置解密密钥, 程序调用mp4decrpyt/shaka-packager/ffmpeg进行解密. 格式:\r\n--key KID1:KEY1 --key KID2:KEY2\r\n对于KEY相同的情况可以直接输入 --key KEY", IsRequired = false, ProcessorType = typeof(StringArrayValueProcessor))]
    public string[]? Keys { get; set; }

    [Argument("base-url", Description = "设置BaseURL", IsRequired = false)]
    public string? BaseUrl { get; set; }

    [Argument("key-text-file", Description = "设置密钥文件,程序将从文件中按KID搜寻KEY以解密.(不建议使用特大文件)", IsRequired = false)]
    public string? KeyTextFile { get; set; }
 
    [Argument("urlprocessor-args", Description = "此字符串将直接传递给URL Processor", IsRequired = false)]
    public string? UrlProcessorArgs { get; set; }
 
    [Argument("log-level", Description = "设置日志级别", IsRequired = false,DefaultValue = LogLevel.INFO)]
    public LogLevel LogLevel { get; set; } = LogLevel.INFO;

    [Argument("no-date-info", Description = "混流时不写入日期信息", IsRequired = false,DefaultValue = true)]
    public bool NoDateInfo { get; set; }
 
    [Argument("allow-hls-multi-ext-map", Description = "允许HLS中的多个#EXT-X-MAP(实验性)", IsRequired = false, DefaultValue = false)]
    public bool AllowHlsMultiExtMap { get; set; }
 
    [Argument("auto-select", Description = "自动选择所有类型的最佳轨道", IsRequired = false, DefaultValue = false)]
    public bool AutoSelect { get; set; }
 
    [Argument("sub-only", Description = "只选取字幕轨道", IsRequired = false, DefaultValue = false)]
    public bool SubOnly { get; set; }
 
    [Argument("thread-count", Description = "设置下载线程数", IsRequired = false,DefaultValue = 8 )]
    public int ThreadCount { get; set; } = Environment.ProcessorCount;
 
    [Argument("download-retry-count", Description = "每个分片下载异常时的重试次数", IsRequired = false,DefaultValue = 3)]
    public int DownloadRetryCount { get; set; } = 3;
 
    [Argument("http-request-timeout", Description = "HTTP请求的超时时间(秒)", IsRequired = false,DefaultValue = 100)]
    public double HttpRequestTimeout { get; set; } = 100;

    [Argument("binary-merge", Description = "检测到fMP4，自动开启二进制合并", IsRequired = false, DefaultValue = false)]
    public bool BinaryMerge { get; set; }

    [Argument("use-ffmpeg-concat-demuxer", Description = "使用 ffmpeg 合并时，使用 concat 分离器而非 concat 协议", IsRequired = false, DefaultValue = false)]
    public bool UseFFmpegConcatDemuxer { get; set; }

    [Argument("del-after-done", Description = "完成后删除临时文件", IsRequired = false, DefaultValue = true)]
    public bool DelAfterDone { get; set; }
 
    [Argument("auto-subtitle-fix", Description = "自动修正字幕", IsRequired = false, DefaultValue = true)]
    public bool AutoSubtitleFix { get; set; }

    [Argument("write-meta-json", Description = "解析后的信息是否输出json文件", IsRequired = false, DefaultValue = true)]
    public bool WriteMetaJson { get; set; }
 
    [Argument("append-url-params", Description = "将输入Url的Params添加至分片, 对某些网站很有用, 例如 kakao.com", IsRequired = false, DefaultValue = false)]
    public bool AppendUrlParams { get; set; }
 
    [Argument("check-segments-count", Description = "检测实际下载的分片数量和预期数量是否匹配", IsRequired = false,DefaultValue = false)]
    public bool CheckSegmentsCount { get; set; }
    [Argument("mp4-real-time-decryption", Description = "实时解密MP4分片", IsRequired = false, DefaultValue = false)]
    public bool MP4RealTimeDecryption { get; set; }
    [Argument("decryption-engine", Description = "设置解密时使用的第三方程序", IsRequired = false)]
    public DecryptEngine DecryptionEngine { get; set; }
    [Argument("mux-after-done", DefaultValue = false, Description = "所有工作完成时尝试混流分离的音视频. 你能够以:分隔形式指定如下参数:\\r\\n\\r\\n\" +\r\n                  \"* format=FORMAT: 指定混流容器 mkv, mp4, ts\\r\\n\" +\r\n                  \"* muxer=MUXER: 指定混流程序 ffmpeg, mkvmerge (默认: ffmpeg)\\r\\n\" +\r\n                  \"* bin_path=PATH: 指定程序路径 (默认: 自动寻找)\\r\\n\" +\r\n                  \"* skip_sub=BOOL: 是否忽略字幕文件 (默认: false)\\r\\n\" +\r\n                  \"* keep=BOOL: 混流完成是否保留文件 true, false (默认: false)\\r\\n\\r\\n\" +\r\n                  \"例如: \\r\\n\" +\r\n                  \"# 混流为mp4容器\\r\\n\" +\r\n                  \"-M format=mp4\\r\\n\" +\r\n                  \"# 使用mkvmerge, 自动寻找程序\\r\\n\" +\r\n                  \"-M format=mkv:muxer=mkvmerge\\r\\n\" +\r\n                  \"# 使用mkvmerge, 自定义程序路径\\r\\n\" +\r\n                  \"-M format=mkv:muxer=mkvmerge:bin_path=\\\"C\\\\:\\\\Program Files\\\\MKVToolNix\\\\mkvmerge.exe", IsRequired = false)]
    public bool MuxAfterDone { get; set; }
    [Argument("sub-format", Description = "字幕输出类型", IsRequired = false, DefaultValue = SubtitleFormat.SRT)]
    public SubtitleFormat SubtitleFormat { get; set; }

    [Argument("tmp-dir", Description = "设置临时文件存储目录", IsRequired = true)]
    public string? TmpDir { get; set; }

    [Argument("save-dir", Description = "设置输出目录", IsRequired = true)]
    public string? SaveDir { get; set; }

    [Argument("save-name", Description = "设置保存文件名", IsRequired = true)]
    public string? SaveName { get; set; }

    [Argument("save-pattern", Description = "设置保存文件命名模板, 支持使用变量", IsRequired = false)]
    public string? SavePattern { get; set; }
 
    [Argument("decryption-binary-path", Description = @"MP4解密所用工具的全路径, 例如 C:\Tools\mp4decrypt.exe", IsRequired = false)]
    public string? DecryptionBinaryPath { get; set; }
 
    [Argument("ffmpeg-binary-path", Description = @"fmpeg可执行程序全路径, 例如 C:\Tools\ffmpeg.exe", IsRequired = false)]
    public string? FFmpegBinaryPath { get; set; }
 
    [Argument("", Description = @"mkvmerge可执行程序全路径, 例如 C:\Tools\mkvmerge.exe", IsRequired = false)]
    public string? MkvmergeBinaryPath { get; set; }
 
    [Argument("select-video", Description = "通过正则表达式选择符合要求的视频流. 你能够以:分隔形式指定如下参数:\r\n\r\n" +
                  "id=REGEX:lang=REGEX:name=REGEX:codecs=REGEX:res=REGEX:frame=REGEX\r\n" +
                  "segsMin=number:segsMax=number:ch=REGEX:range=REGEX:url=REGEX\r\n" +
                  "plistDurMin=hms:plistDurMax=hms:bwMin=int:bwMax=int:role=string:for=FOR\r\n\r\n" +
                  "* for=FOR: 选择方式. best[number], worst[number], all (默认: best)\r\n\r\n" +
                  "例如: \r\n" +
                  "# 选择最佳视频\r\n" +
                  "--select-video best\r\n" +
                  "# 选择4K+HEVC视频\r\n" +
                  "--select-video res=\"3840*\":codecs=hvc1:for=best\r\n" +
                  "# 选择长度大于1小时20分钟30秒的视频\r\n" +
                  "--select-video plistDurMin=\"1h20m30s\":for=best\r\n" +
                  "--select-video role=\"main\":for=best\r\n" +
                  "# 选择码率在800Kbps至1Mbps之间的视频\r\n" +
                  "--select-video bwMin=800:bwMax=1000\r\n", IsRequired = false, ProcessorType = typeof(StreamFilterValueProcessor))]
    public StreamFilter? VideoFilter { get; set; }

    [Argument("drop-video", Description = "通过正则表达式去除符合要求的视频流", IsRequired = false, ProcessorType = typeof(StreamFilterValueProcessor))]
    public StreamFilter? DropVideoFilter { get; set; }

    [Argument("select-audio", Description = "通过正则表达式选择符合要求的音频流. 参考 --select-video\r\n\r\n" +
                  "例如: \r\n" +
                  "# 选择所有音频\r\n" +
                  "--select-audio all\r\n" +
                  "# 选择最佳英语音轨\r\n" +
                  "--select-audio lang=en:for=best\r\n" +
                  "# 选择最佳的2条英语(或日语)音轨\r\n" +
                  "--select-audio lang=\"ja|en\":for=best2\r\n" +
                  "--select-audio role=\"main\":for=best\r\n", IsRequired = false, ProcessorType = typeof(StreamFilterValueProcessor))]
    public StreamFilter? AudioFilter { get; set; }

    [Argument("drop-audio", Description = "通过正则表达式去除符合要求的音频流", IsRequired = false, ProcessorType = typeof(StreamFilterValueProcessor))]
    public StreamFilter? DropAudioFilter { get; set; }
 
    [Argument("select-subtitle", Description = "通过正则表达式选择符合要求的字幕流. 参考 --select-video\r\n\r\n" +
                  "例如: \r\n" +
                  "# 选择所有字幕\r\n" +
                  "--select-subtitle all\r\n" +
                  "# 选择所有带有\"中文\"的字幕\r\n" +
                  "--select-subtitle name=\"中文\":for=all\r\n", IsRequired = false, ProcessorType = typeof(StreamFilterValueProcessor))]
    public StreamFilter? SubtitleFilter { get; set; }
 
    [Argument("drop-subtitle", Description = "通过正则表达式去除符合要求的字幕流", IsRequired = false, ProcessorType = typeof(StreamFilterValueProcessor))]
    public StreamFilter? DropSubtitleFilter { get; set; }
 
    [Argument("custom-hls-method", Description = "指定HLS加密方式 (AES_128|AES_128_ECB|CENC|CHACHA20|NONE|SAMPLE_AES|SAMPLE_AES_CTR|UNKNOWN)", IsRequired = false, DefaultValue = EncryptMethod.NONE)]
    public EncryptMethod? CustomHLSMethod { get; set; }
 
    [Argument("custom-hls-key", Description = "指定HLS解密KEY. 可以是文件, HEX或Base64", IsRequired = false, ProcessorType = typeof(ByteArrayValueProcessor))]
    public byte[]? CustomHLSKey { get; set; }
 
    [Argument("custom-hls-iv", Description = "指定HLS解密IV. 可以是文件, HEX或Base64", IsRequired = false, ProcessorType = typeof(ByteArrayValueProcessor))]
    public byte[]? CustomHLSIv { get; set; }
    [Argument("MuxOptions", Description = "无描述说明，源码中没有提供", IsRequired = false)]

    public MuxOptions? MuxOptions { get; set; }
}